﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Device.Location;
using System.Windows.Threading;
using System.Diagnostics;
using Microsoft.Phone.Shell;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Media;
using System.Text;

namespace SpeedRun
{
    public partial class Runner : PhoneApplicationPage
    {
        #region Decelrations
        GeoCoordinateWatcher geo;        
        GeoPositionStatus currentStatus { get; set; }

        double currentSpeedVar
        {
            get
            {
                if (currentSpeed.Text == String.Empty || currentSpeed.Text == null)
                {
                    return 0;
                }
                else
                    if (currentSpeed.Text.Length > 4)
                        return Convert.ToDouble(currentSpeed.Text.Remove(currentSpeed.Text.Length - 4));
                    else
                        return Convert.ToDouble(currentSpeed.Text);
            }
            set
            {
                value = value * 4.5;
                if (value != double.NaN && !double.IsNaN(value))
                {
                    if (value.ToString().Length > 4)
                        currentSpeed.Text = value.ToString().Remove(4) + " mph";
                    else
                        currentSpeed.Text = value.ToString() + " mph";
                }
                else
                    currentSpeed.Text = "0" + " mph"; 
            }
        }
        double currentDistanceVar
        {
            get
            {
                try
                {
                    return Convert.ToDouble(Distance.Text.Trim('m'));
                }
                catch (Exception _e)
                {
                    return 0;
                }
            }
            set
            {
                try
                {
                    if (value.ToString().Length > 4)
                    {
                        Distance.Text = value.ToString().Remove(4) + " m";
                    }

                    else
                        if (double.IsNaN(value))
                            Distance.Text = "0" + " m";

                        else
                            Distance.Text = value.ToString() + " m";

                }
                catch (Exception _e)
                {
                   
                }
            }
        }
        double Alt;
        MediaElement me;
        DispatcherTimer timer = new DispatcherTimer();        
        Stopwatch stopWatch;
        long dd = 0, hh = 0, mm = 0, ss = 0, ms = 0;
        List<double> speedAnalysis = new List<double>();
        List<double> DistanceAnalysis = new List<double>();
        public static List<GeoCoordinate> CoordinatesCovered = new List<GeoCoordinate>();
        bool _finished = false;
        double Cal;
        double caloriesz
        {
            get
            {
                var user = (App.Current as App).currentUser;
                switch ((App.Current as App).currentUser.type)
                {
                    case BodyType.Fit:
                    case BodyType.Muscular:
                    case BodyType.Athletic:
                        Cal += user.Weight * currentSpeedVar * Alt * 2 * 0.01;
                        break;

                    case BodyType.Fat:
                    case BodyType.Aged:
                        Cal += user.Weight * currentSpeedVar * Alt * 2 * 0.01;
                        break;

                    case BodyType.Slim:
                        Cal += user.Weight * currentSpeedVar * Alt * 2 * 0.01;
                        break;
                }
                return Cal;
            }
        }
        RunTypes currentRunType = RunTypes.None;
        #endregion
        public Runner()
        {
            geo = (App.Current as App).geo;
            InitializeComponent();
            #region Crappy stuff
            // Check if 'allow' setting already set
            bool? allow = null;
            if (PhoneApplicationService.Current.State.ContainsKey("allow"))
            {
                allow = (bool)PhoneApplicationService.Current.State["allow"];
            }

            if (allow == null)
            {
                // 'allow' setting not set yet (i.e. it is first page load)
                // Display the confirmation question
                var result = MessageBox.Show(
                               "This application uses your location. Do you wish " +
                               "to give it permission to use your location?",
                               "User Location Data",
                               MessageBoxButton.OKCancel);

                // Save answer so you can access it on other pages 
                allow = (result == MessageBoxResult.OK);
                PhoneApplicationService.Current.State["allow"] = allow;
            }

            if (allow.Value)
            {
                // Initiate your app normally
            }
            else
            {
                new Game().Exit();
            }

            #endregion
            stopWatch = new Stopwatch();
            InitializeComponent();
            try
            {
                geo.PositionChanged += new System.EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(geo_PositionChanged);
                geo.StatusChanged += new System.EventHandler<GeoPositionStatusChangedEventArgs>(geo_StatusChanged);
                geo.TryStart(true, TimeSpan.FromMilliseconds(100));
                geo.MovementThreshold = 0.000001;
                progressBar.Visibility = System.Windows.Visibility.Visible;
            }
            catch (Exception __e)
            {
                MessageBox.Show("Your App does not have GPS! This app will not run on this Phone!");
                new Game().Exit();
            }
            me = new MediaElement();
            me.CurrentStateChanged += new RoutedEventHandler(me_CurrentStateChanged);
            me.MediaEnded += new RoutedEventHandler(me_MediaEnded);
            timer.Interval = TimeSpan.FromMilliseconds(50);
            timer.Tick += new System.EventHandler(timer_Tick);
        }
        #region Navigation
        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            currentRunType = (App.Current as App).currentRunType;
            if (geo.Status == GeoPositionStatus.NoData || geo.Status == GeoPositionStatus.Disabled)
                geo.TryStart(true, TimeSpan.FromMilliseconds(50));
            base.OnNavigatedTo(e);
        }
        protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
        {
            geo.Stop();
            
            base.OnNavigatedFrom(e);
        }
        #endregion
        #region MediaElement Crap
        void me_MediaEnded(object sender, RoutedEventArgs e)
        {
            LayoutRoot.Children.Remove(me);
            MediaPlayer.Resume();
        }
        private void reAssignChildren()
        {
            if (LayoutRoot.Children.Contains(me))
                LayoutRoot.Children.ToString();
            else
                LayoutRoot.Children.Add(me);
        }
        void me_CurrentStateChanged(object sender, RoutedEventArgs e)
        {
            var me = sender as MediaElement;


            if (me.CurrentState == MediaElementState.Stopped || me.CurrentState == MediaElementState.Closed)
                LayoutRoot.Children.Remove(me);

            if (me.CurrentState == MediaElementState.Playing)
            {
                if (MediaPlayer.State == MediaState.Playing)
                    MediaPlayer.Volume -= 0.4f;
            }
            else
                if(me.CurrentState == MediaElementState.Paused)
                    if(MediaPlayer.State ==
                         MediaState.Playing)
                        MediaPlayer
                            .Volume += 0.4f;
        }
        #endregion
        #region Geo Crap!
        void timer_Tick(object sender, System.EventArgs e)
        {
            ms = stopWatch.ElapsedMilliseconds;
            ss = ms / 1000;
            ms = ms % 1000;
            mm = ss / 60;
            ss = ss % 60;
            dd = hh / 24;
            hh = hh % 24;

                Dispatcher.BeginInvoke(() =>
                    {
                        currentDistanceVar += currentSpeedVar;
                        time.Text = hh + ":" + mm + ":" + ss + ":" + ms;
                        calories.Text = (caloriesz.ToString().Length > 4 ? caloriesz.ToString().Remove(4) : caloriesz.ToString()) + " KCal" ;
                    }
                );

            if((App.Current as App).currentRunType == RunTypes.Time)
                if ((App.Current as App).runTime <= new TimeSpan((int)hh, (int)mm, (int)ss))
                {
                    Image img = new Image();
                    img.Name = "stopImg";
                    Image_Tap(img, new System.Windows.Input.GestureEventArgs());                
                }
        }

        void geo_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
        {
            currentStatus = e.Status;
            switch (e.Status)
            {
                case GeoPositionStatus.Ready: indicator.Fill = new SolidColorBrush(System.Windows.Media.Color.FromArgb(100, 0, 255, 0));
                    progressBar.Visibility = System.Windows.Visibility.Collapsed;
                    calories.Text = "0 Cal";
                    time.Text = "0 sec";
                    distance.Text = "0 m";
                    currentSpeedVar = 0;
                    break;
                case GeoPositionStatus.Initializing: indicator.Fill = new SolidColorBrush(System.Windows.Media.Color.FromArgb(100, Microsoft.Xna.Framework.Color.Yellow.R, Microsoft.Xna.Framework.Color.Yellow.G, Microsoft.Xna.Framework.Color.Yellow.B));
                    break;
                case GeoPositionStatus.NoData: indicator.Fill = new SolidColorBrush(System.Windows.Media.Color.FromArgb(100, 255, 0, 0));
                    break;
                case GeoPositionStatus.Disabled: MessageBox.Show("Your App does not have GPS! This app will not run on this Phone!");
                    progressBar.Visibility = System.Windows.Visibility.Collapsed;
                    new Game().Exit();
                    break;
            }

            Dispatcher.BeginInvoke(delegate()
            {
                if (e.Status == GeoPositionStatus.Initializing)
                    statusMsg.FontSize = 16;
                else
                    statusMsg.FontSize = 20;
                statusMsg.Text = e.Status.ToString();
                Process();
            }
            );
        }


        void geo_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
        {
            if (currentStatus == GeoPositionStatus.Ready)
            {                
                currentLocation.Text = e.Position.Location.Latitude.ToString().Remove(4) + "' " + e.Position.Location.Longitude.ToString().Remove(4) + "''";
                currentSpeedVar = e.Position.Location.Speed;
                speedAnalysis.Add(currentSpeedVar);
                Alt = e.Position.Location.Altitude;
                Runner.CoordinatesCovered.Add(e.Position.Location);
            }
        }
        #endregion
        #region UI Events


        private void TitlePanel_Loaded(object sender, RoutedEventArgs e)
        {
            time.Text = "00:00:00";
        }

        private void Image_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
            //if (currentStatus != GeoPositionStatus.Ready)
            //{
            //    MessageBox.Show("Please wait GPS/Location service has not yet been established!");
            //    return;
            //}
           

            var img = sender as Image;

            if (img.Name != "stopImg")
            {
                if ((App.Current as App).currentRunType == RunTypes.Distance)
                {
                    Microsoft.Phone.Tasks.BingMapsDirectionsTask directions = new Microsoft.Phone.Tasks.BingMapsDirectionsTask();
                    directions.Start = new Microsoft.Phone.Tasks.LabeledMapLocation("Start", new GeoCoordinate(this.geo.Position.Location.Latitude, this.geo.Position.Location.Longitude));
                    double i = 0.000001;
                    GeoCoordinate endCoord = new GeoCoordinate();
                    endCoord = directions.Start.Location;
                    endCoord.Longitude += 0.0001;


                    double dist = directions.Start.Location.GetDistanceTo(endCoord);
                    
                    while (!(dist >= ((App.Current as App).distTarget)))
                    {
                        endCoord.Latitude += i;
                        endCoord.Longitude += i;
                        dist = directions.Start.Location.GetDistanceTo(endCoord);
                        endCoord = new GeoCoordinate(endCoord.Latitude + i, endCoord.Longitude + i);

                        i += new Random().NextDouble() * 0.0000001;
                    }

                    directions.End = new Microsoft.Phone.Tasks.LabeledMapLocation("End", endCoord);                    
                    directions.Show();
                }
                SongCollection songs;
                using (MediaLibrary lib = new MediaLibrary())
                {
                    songs = lib.Songs;
                }
                if(MediaPlayer.State != MediaState.Playing)
                    MediaPlayer.Play(songs, new Random().Next(0, songs.Count));
                timer.Start();
                stopWatch.Start();
                songName.Text = MediaPlayer.Queue.ActiveSong.Name + "\n" + MediaPlayer.Queue.ActiveSong.Artist;
                MediaPlayer.ActiveSongChanged += new EventHandler<EventArgs>(MediaPlayer_ActiveSongChanged);
                Stop.Visibility = System.Windows.Visibility.Visible;
                playImage.Visibility = System.Windows.Visibility.Collapsed;

                me.Source = (App.Current as App).sounds[2];
                reAssignChildren();
                me.Play();
            }
            else
            {
                timer.Stop();
                MediaPlayer.Stop();
                stopWatch.Stop();
                double sum = 0;

                foreach (double dble in speedAnalysis)
                {
                    sum += dble;
                }

                sum /= speedAnalysis.Capacity;
                if (sum.ToString() == "NaN" || double.IsNaN(sum))
                {
                    avgSpeed.Text = "0";
                    sum = 0;
                }
                else
                    if (sum.ToString().Length > 4)
                        avgSpeed.Text = sum.ToString().Remove(4);

                            else
                                avgSpeed.Text = sum.ToString();

                TimeSpan ts = new System.TimeSpan((int)dd, (int)hh, (int)mm, (int)ss, (int)ms);
                distance.Text = ((sum * ts.Minutes) > 50 ? (sum * ts.Minutes) : (sum * ts.Seconds)).ToString();

                if (Double.IsNaN(Convert.ToDouble(distance.Text)))
                    distance.Text = "0";


                if (speedAnalysis.
                    Capacity > 1)
                    maxSpeed.Text = speedAnalysis.Max().ToString();


                _finished = true;
                Process();
                summary.Visibility = System.Windows.Visibility.Visible;
                playImage.Visibility = System.Windows.Visibility.Visible;
                Stop.Visibility = System.Windows.Visibility.Collapsed;
                Run.SaveHistory(new Run()
                {
                    runType = (App.Current as App).currentRunType,
                    speed = Convert.ToDouble(avgSpeed.Text),
                    time = ts,
                    user = (App.Current as App).currentUser,
                    coordinates = Runner.CoordinatesCovered,
                    calories = caloriesz,
                    TimeStamp = System.DateTime.Now
                });
                
            }

        }

        void MediaPlayer_ActiveSongChanged(object sender, EventArgs e)
        {
            songName.Text = MediaPlayer.Queue.ActiveSong.Name + "\n" + MediaPlayer.Queue.ActiveSong.Artist;
        }

        private void Image_Tap_1(object sender, System.Windows.Input.GestureEventArgs e)
        {
            timer.Stop();
            MediaPlayer.Pause();
            stopWatch.Stop();

            summary.Visibility = System.Windows.Visibility.Collapsed;
        }


        private void rr_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
            MediaPlayer.MovePrevious();
            songName.Text = MediaPlayer.Queue.ActiveSong.Name + "\n" + MediaPlayer.Queue.ActiveSong.Artist;
        }

        private void ff_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
            MediaPlayer.MoveNext();
            songName.Text = MediaPlayer.Queue.ActiveSong.Name + "\n" + MediaPlayer.Queue.ActiveSong.Artist;
        }

        private void Image_Hold(object sender, System.Windows.Input.GestureEventArgs e)
        {

        }

        private void Image_Hold_1(object sender, System.Windows.Input.GestureEventArgs e)
        {

        }



        private void Image_ImageFailed(object sender, ExceptionRoutedEventArgs e)
        {

        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            NavigationService.Navigate(new System.Uri("/Profile.xaml", System.UriKind.RelativeOrAbsolute));
        }


      

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            NavigationService.Navigate(new Uri
            ("/SongSelector.xaml",
             UriKind.RelativeOrAbsolute));
        }

        private void indicator_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
            geo.TryStart(true, TimeSpan.FromMilliseconds(50));
        }
        #endregion
        #region Main Algo
        void Process()
        {
            try
            {
                var avg = Convert.ToDouble(avgSpeed.Text);
                var dist = Convert.ToDouble(distance.Text);
                var time = Convert.ToDouble(ss);


            }
            catch (Exception e)
            { }


            var profile = User.UserRetrive();
            if (profile.gender == Gender.male)
            {
                //if (profile.Age > 60)
                {
                    if (me.Source == null)
                        me.Source = (App.Current as App).sounds[1];

                    if (new Random().Next(0, 1000) > 5 && me.CurrentState != MediaElementState.Playing)
                    {
                        me.Source = (App.Current as App).sounds[1];
                        reAssignChildren();
                        me.Play();
                    }

                    if (currentSpeedVar > 3 && me.CurrentState != MediaElementState.Playing)
                        if (new Random().Next(0, 10) > 8)
                        {
                            me.Source = (App.Current as App).sounds[1];
                            reAssignChildren();
                            me.Play();
                        }

                    if (currentSpeedVar < 0.3 && me.CurrentState != MediaElementState.Playing)
                    {
                        me.Source = (App.Current as App).sounds[5];
                        reAssignChildren();
                        me.Play();
                    }

                    if (_finished && me.CurrentState != MediaElementState.Playing)
                    {
                        me.Source = (App.Current as App).sounds[4];
                        reAssignChildren();
                        me.Play();
                    }

                }


            }

            else
            {
                me.Source = (App.Current as App).sounds[3];
                reAssignChildren();
                me.Play();
            }




            if (_finished)
            {
                reAssignChildren();
                me.Source = (App.Current as App).sounds[4]; reAssignChildren();
                me.Play();


                me.Source = (App.Current as App).sounds[3];
                reAssignChildren();
                me.Play();


                StringBuilder sb = new StringBuilder();
                if (Convert.ToDouble(avgSpeed.Text) > 0.7 && (Convert.ToDouble(distance.Text) > 1000))
                    sb.Append("You have maintained a good average Speed! Over a long distance");

                if (Convert.ToDouble(avgSpeed.Text) > 2)
                    sb.Append("Whoa! great speed!");

                if (Convert.ToDouble(currentDistanceVar) > 2000)
                    sb.Append("More than 2 Kilometers!");

                if (Convert.ToDouble(currentDistanceVar) < 600)
                    sb.Append("You can do better than this!");

                Comments.Text = sb.ToString();


                if ((App.Current as App).currentRunType == RunTypes.Time)
                {
                    NavigationService.Navigate(new Uri("/Facebook.xaml", UriKind.RelativeOrAbsolute));
                }
            }
        }
        #endregion


    }
}